import fs from 'fs';
import path from 'path';
export interface BaseModel {
  id?: number;
  createdAt?: string;
  updatedAt?: string;
}

export class FileStorage<T extends BaseModel> {
  private filePath: string;
  private data: T[] = [];
  private lastId = 0;

  constructor(fileName: string) {
    // 确保 data 目录存在
    const dataDir = path.join(process.cwd(), 'data');
    if (!fs.existsSync(dataDir)) {
      fs.mkdirSync(dataDir, { recursive: true });
    }

    this.filePath = path.join(dataDir, fileName);
    this.loadData();
  }

  private loadData(): void {
    try {
      if (fs.existsSync(this.filePath)) {
        const fileContent = fs.readFileSync(this.filePath, 'utf-8');
        this.data = JSON.parse(fileContent);
        // 找到最大的 id
        this.lastId = Math.max(0, ...this.data.map(item => item.id || 0));
      } else {
        this.data = [];
        this.saveData();
      }
    } catch (error) {
      console.error('加载数据失败:', error);
      this.data = [];
    }
  }

  private saveData(): void {
    try {
      fs.writeFileSync(this.filePath, JSON.stringify(this.data, null, 2));
    } catch (error) {
      console.error('保存数据失败:', error);
    }
  }

  create(item: Omit<T, 'id' | 'createdAt' | 'updatedAt'>): number {
    const newId = ++this.lastId;
    const newItem = {
      ...item,
      id: newId,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    } as T;

    this.data.push(newItem);
    this.saveData();
    return newId;
  }

  findById(id: number): T | undefined {
    return this.data.find(item => item.id === id);
  }

  findAll(): T[] {
    return [...this.data];
  }

  findOne(predicate: (item: T) => boolean): T | undefined {
    return this.data.find(predicate);
  }

  update(id: number, updates: Partial<T>): boolean {
    const index = this.data.findIndex(item => item.id === id);
    if (index === -1) return false;

    this.data[index] = {
      ...this.data[index],
      ...updates,
      updatedAt: new Date().toISOString()
    } as T;

    this.saveData();
    return true;
  }

  delete(id: number): boolean {
    const initialLength = this.data.length;
    this.data = this.data.filter(item => item.id !== id);
    
    if (this.data.length !== initialLength) {
      this.saveData();
      return true;
    }
    return false;
  }

  count(predicate?: (item: T) => boolean): number {
    if (predicate) {
      return this.data.filter(predicate).length;
    }
    return this.data.length;
  }
}

/**
 * 从文件末尾逆向读取行
 * @param filePath 文件路径
 * @returns 异步迭代器，每次返回一行
 */
export async function* reverseReadLines(filePath: string): AsyncGenerator<string> {
  let fd = -1;
  try {
    // 打开文件
    fd = fs.openSync(filePath, 'r');
    const stats = fs.fstatSync(fd);
    const fileSize = stats.size;
    console.log('filePath', filePath);
    console.log('fileSize', fileSize);

    let currentPos = fileSize;
    const chunkSize = 1024 * 64; // 64KB 块大小
    let lastLine = '';
    let isFirstChunk = true;

    // 从文件末尾开始循环读取,直到到达文件开头
    while (currentPos > 0) {
      // 计算当前块的起始位置和大小
      const start = Math.max(currentPos - chunkSize, 0);
      const readSize = currentPos - start;
      
      // 读取一个块的数据
      const buf = Buffer.alloc(readSize);
      await new Promise((resolve, reject) => {
        fs.read(fd, buf, 0, readSize, start, (err, bytesRead) => {
          if (err) reject(err);
          else resolve(bytesRead);
        });
      });
      
      // 将二进制数据转换为字符串
      let chunk = buf.toString('utf8');

      // 如果不是第一个块，找到第一个完整的换行符
      if (!isFirstChunk) {
        const newlineIndex = chunk.lastIndexOf('\n');
        if (newlineIndex !== -1) {
          // 将这个块的最后一部分添加到上一个不完整的行
          lastLine = chunk.substring(newlineIndex + 1) + lastLine;
          // 只保留到最后一个换行符的内容
          chunk = chunk.substring(0, newlineIndex);
        } else {
          // 如果没有换行符，整个块都是上一行的一部分
          lastLine = chunk + lastLine;
          chunk = '';
        }
      }

      // 处理当前块的完整行
      const lines = chunk.split('\n').reverse();
      
      // 如果有上一个不完整的行，先输出它
      if (lastLine && lines.length > 0) {
        const completeLine = lines[0] + lastLine;
        if (completeLine.trim()) {
          yield completeLine.trim();
        }
      }

      // 输出其他完整的行
      for (let i = isFirstChunk ? 0 : 1; i < lines.length; i++) {
        const line = lines[i].trim();
        if (line) {
          yield line;
        }
      }

      // 保存这个块的第一行（可能不完整）到下一次迭代
      if (lines.length > 0) {
        lastLine = lines[lines.length - 1];
      }

      currentPos = start;
      isFirstChunk = false;
    }

    // 处理最后一行（如果有的话）
    if (lastLine && lastLine.trim()) {
      yield lastLine.trim();
    }
  } catch (err) {
    console.error('读取文件失败:', err);
    throw err;
  } finally {
    if (fd >= 0) {
      fs.closeSync(fd);
    }
  }
}